﻿
//VERSION 1.0


//BUGS
//-LABS ARE RETURNING HTML TAGS i.e spaces(&nbsp) I.E &nbsp&nbsp&nbsp&nbsp&nbsp: YK
//-LAB WEEKS ARE NOT WORKING  THEY ALL RETURN 0
//-THE START TIME DATA MEMBER RETURNS A COMMA IN IT I.E 17,:00
//-lectures are only returning 1 day of the week rather than 2 I.E TUESDAY


//List of Exceptions Occuring 
//-IF A COURSE HAS NO TUTORIAL
//-IF A COURSE HAS NO LAB
//-IF A COURSE HAS A LAB AND NO TUTORIAL
//-IF A COURSE HAS A TUTORIAL AND NO LAB
//-IF A COURSE DOESN'T EXIST
//-ONLINE CLASSES

//Test Application in the root folder its made intu a win32 console application!
//I noticed someone put an excel file of all the classes i figured you can get any class information without having to click it  and you can just parse it directly and the link will just update every year

//http://fcms.concordia.ca/fcms/asc002_stud_all.aspx?yrsess=2009X&course=Y&courno=Z%20&campus=&type=U

//before the x you can see there is 2009, you can change this to anything just needs 4 digits.
//you can just use this url: and change X value to semester number(1,2,4)summer,fall,winter,
//change Y value to course  i.e SOEN
//and change Z value to course number i.e 341

//i.e for soen341 in fall semester it would look like this
//http://fcms.concordia.ca/fcms/asc002_stud_all.aspx?yrsess=20092&course=SOEN&courno=341%20&campus=&type=U

/*
  The schedule page has one big table with all the results, regardless of the number of results. This main table has this XPATH:   //*[@id="ctl00_PageBody_tblBodyShow1"]
  Each listed course is not a table in itself, it's just a row. In fact, everything in that table is just a sibling, regardless of its logical importance. 
  The only thing that distinguishes the row that gives title of the course from the row that shows its prerequisites seems to be:
    -> its colour:      <tr align="left" style="background-color:LightBlue;">
	-> number of coloumns: 4
    -> contents: the last column seems to always have the word 'credits' in there somewhere
  
  When these 3 elements are met, that specific row should be the title-of-the-course row.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Threading;
using HtmlAgilityPack;
using System.Runtime.Serialization;
using System.Xml.Serialization;
using System.Xml.Linq;
using System.Xml;

namespace myScheduler
{
    public class combo
    {
        public List<uniqueSequence> comboMembers = new List<uniqueSequence>();
        public List<timeBlock> combinedTime = new List<timeBlock>();

    }

    public class uniqueSequence
    {
        public course cour;
        public lecture lect;
        public tutorial tut;
        public lab lab;
    }

    public class WebScraper
    {
        public static List<combo> generate(List<string> courses)
        {
            try
            {
                List<course> courseObj = new List<course>();
                foreach (string c in courses)
                {

                    string sql_command = string.Format("SELECT course_object_XML FROM Course_Object3 WHERE course_code + ' ' + course_number = '{0}'", c);
                    List<String> gotten = SQLcontrol.SQLreadXML(sql_command);

                    course tempC;
                    if (gotten.Count != 0)
                    {
                        tempC = deserializeCourse(XElement.Parse(gotten[0]));
                    }
                    else
                    {
                        return null;
                    }

                    courseObj.Add(tempC);
                }
                return (feeder(courseObj));
            }
            catch (ArgumentNullException e2)
            {
                return null;
            }
        }


        public static List<combo> unwrapper(course c)
        {
            List<combo> result = new List<combo>();

            for (int i = 0; i < c.lectures.Count; i++)
            {
                for (int j = 0; j < c.lectures[i].tutorials.Count; j++)
                {
                    if (c.lectures[i].tutorials[j].labs.Count > 0)
                    {
                        for (int k = 0; k < c.lectures[i].tutorials[j].labs.Count; k++)
                        {
                            combo tempCombo = new combo();
                            uniqueSequence tempSequence = new uniqueSequence();
                            tempSequence.cour = c;
                            tempSequence.lect = c.lectures[i];
                            tempSequence.tut = c.lectures[i].tutorials[j];
                            tempSequence.lab = c.lectures[i].tutorials[j].labs[k];
                            tempCombo.comboMembers.Add(tempSequence);

                            for (int l = 0; l < c.lectures[i].time.Count; l++)
                            {
                                tempCombo.combinedTime.Add(c.lectures[i].time[l]);

                            }

                            for (int p = 0; p < c.lectures[i].tutorials[j].time.Count; p++)
                            {
                                tempCombo.combinedTime.Add(c.lectures[i].tutorials[j].time[p]);
                            }

                            for (int q = 0; q < c.lectures[i].tutorials[j].labs[k].time.Count; q++)
                            {
                                tempCombo.combinedTime.Add(c.lectures[i].tutorials[j].labs[k].time[q]);
                            }
                            result.Add(tempCombo);
                        }
                    }
                    else
                    {
                        combo tempCombo = new combo();
                        uniqueSequence tempSequence = new uniqueSequence();
                        tempSequence.cour = c;
                        tempSequence.lect = c.lectures[i];
                        tempSequence.tut = c.lectures[i].tutorials[j];
                        tempSequence.lab = null;
                        tempCombo.comboMembers.Add(tempSequence);

                        for (int l = 0; l < c.lectures[i].time.Count; l++)
                        {
                            tempCombo.combinedTime.Add(c.lectures[i].time[l]);

                        }

                        for (int p = 0; p < c.lectures[i].tutorials[j].time.Count; p++)
                        {
                            tempCombo.combinedTime.Add(c.lectures[i].tutorials[j].time[p]);
                        }

                        result.Add(tempCombo);



                    }
                }

            }


            return result;
        }

        public static List<combo> feeder(List<course> selected)
        {
            List<combo> result = new List<combo>();
            List<List<combo>> unwrapped = new List<List<combo>>();

            foreach (course s in selected)
            {
                unwrapped.Add(unwrapper(s));
            }

            if (unwrapped.Count == 1)
                return unwrapped[0];
            else
            {

                result = processor(unwrapped[0], unwrapped[1]);

                for (int j = 2; j < (unwrapped.Count); j++)
                {
                    result = processor(result, unwrapped[j]);
                }

            }

            return result;
        }


        public static List<combo> processor(List<combo> a, List<combo> b)
        {
            List<combo> result = new List<combo>();

            for (int j = 0; j < a.Count; j++)
            {
                for (int k = 0; k < b.Count; k++)
                {



                    bool conflict = false;

                    for (int jj = 0; jj < a[j].combinedTime.Count; jj++)
                    {
                        for (int kk = 0; kk < b[k].combinedTime.Count; kk++)
                        {
                            if (a[j].combinedTime[jj].day == b[k].combinedTime[kk].day)
                            {
                                int sA = int.Parse(a[j].combinedTime[jj].startHour) * 60 + int.Parse(a[j].combinedTime[jj].startMinute);
                                int eA = int.Parse(a[j].combinedTime[jj].endHour) * 60 + int.Parse(a[j].combinedTime[jj].endMinute);

                                int sB = int.Parse(b[k].combinedTime[kk].startHour) * 60 + int.Parse(b[k].combinedTime[kk].startMinute);
                                int eB = int.Parse(b[k].combinedTime[kk].endHour) * 60 + int.Parse(b[k].combinedTime[kk].endMinute);

                                if (eA >= sB && eA <= eB)
                                    conflict = true;

                                if (sA >= sB && sA <= sB)
                                    conflict = true;

                                if (sA >= sB && eA <= eB)
                                    conflict = true;

                                if (sB >= sA && eB < eA)
                                    conflict = true;




                            }

                        }

                    }

                    if (conflict == false)
                    {
                        //adding the non-conflicting results
                        combo temp = new combo();
                        for (int l = 0; l < a[j].combinedTime.Count; l++)
                        {
                            temp.combinedTime.Add(a[j].combinedTime[l]);

                        }

                        for (int l = 0; l < b[k].combinedTime.Count; l++)
                        {
                            temp.combinedTime.Add(b[k].combinedTime[l]);
                        }

                        for (int l = 0; l < a[j].comboMembers.Count; l++)
                        {
                            temp.comboMembers.Add(a[j].comboMembers[l]);

                        }
                        for (int l = 0; l < b[k].comboMembers.Count; l++)
                        {
                            temp.comboMembers.Add(b[k].comboMembers[l]);
                        }

                        result.Add(temp);
                    }

                    //if (conflict == false)
                    //{
                    //    //adding the non-conflicting results
                    //    combo temp = new combo();
                    //    for (int jj = 0; jj < a[j].combinedTime.Count; jj++)
                    //    {
                    //        temp.combinedTime.Add(a[j].combinedTime[jj]);
                    //
                    //    }
                    //
                    //    for (int kk = 0; kk < b[k].combinedTime.Count; kk++)
                    //    {
                    //        temp.combinedTime.Add(b[k].combinedTime[kk]);
                    //    }
                    //
                    //    for (int jj = 0; jj < a[j].comboMembers.Count; jj++)
                    //    {
                    //        temp.comboMembers.Add(a[j].comboMembers[jj]);
                    //
                    //    }
                    //    for (int kk = 0; kk < b[k].comboMembers.Count; kk++)
                    //    {
                    //        temp.comboMembers.Add(b[k].comboMembers[kk]);
                    //    }
                    //
                    //}

                }
            }

            return result;
        }


        public static XElement serializeCourse(course c)
        {
            XmlSerializer x = new XmlSerializer(typeof(course));
            XDocument doc = new XDocument();

            using (XmlWriter xw = doc.CreateWriter())
            {
                x.Serialize(xw, c);
                xw.Close();
            }

            XElement el = doc.Root;
            return el;
        }

        public static course deserializeCourse(XElement Xe)
        {
            XmlSerializer x = new XmlSerializer(typeof(course));
            using (XmlReader xr = Xe.CreateReader())
            {
                course deserCourse = new course();
                deserCourse = x.Deserialize(xr) as course;
                xr.Close();
                return deserCourse;
            }
        }




        public HtmlWeb web;
        public HtmlDocument doc;
        public HtmlNodeCollection tables;
        public HtmlNodeCollection rows;
        public HtmlNodeCollection cols;
        public string[] branches = { "ELEC", "BCEE", "CIVI", "BLDG", "ENCS", "ENGR", "IADI", "COMP", "SOEN", "COEN", "INDU", "MECH" };



        public List<course> buildHTMLreturnBranchCourses(string branch)
        {
            string html_path = string.Format("http://fcms.concordia.ca/fcms/asc002_stud_all.aspx?yrsess=20092&course={0}&courno=&campus=&type=U", branch);
            List<course> course_batch = new List<course>();
            course_batch = scrape(html_path);

            return course_batch;


        }


        public List<course> scrape(string input_url)
        {
            web = new HtmlWeb();
            doc = web.Load(input_url);

            //select the tables with all the results
            tables = doc.DocumentNode.SelectNodes("//*[@id=\"ctl00_PageBody_tblBodyShow1\"]");

            rows = tables[0].SelectNodes(".//tr");

            bool firstPass = true;
            List<course> allCourses = new List<course>(); //to be returned

            List<HtmlNode> oneCourse = new List<HtmlNode>(); ;// = null;
            foreach (HtmlNode r in rows)
            {
                course temp = new course();
                if (r.OuterHtml.Contains("bgcolor=\"LightBlue\""))
                {
                    if (firstPass == true)
                    {
                        firstPass = false;
                    }
                    else
                    {
                        //course temp = new course();
                        temp = processCourse(oneCourse);
                        if (temp.validCourse == true)
                        {
                            allCourses.Add(temp);
                        }

                        oneCourse.Clear();
                    }


                    oneCourse.Add(r);

                }
                else
                {
                    if (firstPass == false)
                    {
                        //string temp_string2 = new string(r.OuterHtml.ToString().ToCharArray());
                        oneCourse.Add(r);

                    }
                }

            }
            allCourses.Add(processCourse(oneCourse));

            //processed_data();

            return allCourses;
        }

        public course processCourse(List<HtmlNode> oneCourse) //should receive one block of course, one singele course; that is the title, prereqs, lectures, tutorials, labs, special notes 
        {

            course t = new course();

            t.validCourse = true;

            int k = 0;

            //Title of the course
            HtmlNodeCollection titleCols = oneCourse[k].SelectNodes(".//td"); //first row contains title of the course, number and number of credits
            k++;

            t.numberBranch = titleCols[1].InnerText.Split(new Char[] { ' ' })[0];
            t.numberNumber = titleCols[1].InnerText.Split(new Char[] { ' ' })[1];
            t.name = titleCols[2].InnerText;//.Replace("&nbsp;");
            t.name = t.name.Replace("&nbsp;", "");
            t.credits = float.Parse(titleCols[3].InnerText.Split(new Char[] { ' ' })[0]);


            //Check if the next row describes prereqs
            if (oneCourse[k].SelectNodes(".//td")[1].InnerText == "Prerequisite:")
            {
                t.prereqCourses = (oneCourse[k].SelectNodes(".//td")[2].InnerText);
                k++;
            }

            if (oneCourse[k].SelectNodes(".//td")[1].InnerText == "Special Note:")
            {
                t.specialNote = parseSpecialNote(oneCourse[k].SelectNodes(".//td")[2].InnerText);
                k++;
            }

            k++;

            //process lectures, tutorials, labs... you know, the easy stuff
            bool firstPass = true;
            List<lecture> theLectures = new List<lecture>();
            List<HtmlNode> oneLecture = new List<HtmlNode>();
            for (int j = k; j < oneCourse.Count(); j++) //cycle through all the rows that give the information of lecture
            {

                if (oneCourse[j].SelectNodes(".//td")[2].InnerText.Contains("Lect")) //this row is a lecture row; until the next lecture row or until the end of this course's section, the information is about this lecture's tutorials and labs
                {
                    if (firstPass == true)
                    {
                        firstPass = false;
                        oneLecture.Add(oneCourse[j]);

                    }
                    else
                    {
                        theLectures.Add(parseLecture(oneLecture)); //send one block of lecture to be parsed: a lecture and all it's tutorials and labs
                        oneLecture.Clear();
                        oneLecture.Add(oneCourse[j]);

                    }

                }

                else //this row is another row that is between two lectture rows and will be sent for parsing as part of the oneLecture list.
                {
                    oneLecture.Add(oneCourse[j]);


                }

            }
            theLectures.Add(parseLecture(oneLecture));

            t.lectures = theLectures;

            return t;



            //course t = new course();

            //t.validCourse = true;

            //int k = 0;

            ////Title of the course
            //HtmlNodeCollection titleCols = oneCourse[k].SelectNodes(".//td"); //first row contains title of the course, number and number of credits
            //k++;

            //t.numberBranch = titleCols[1].InnerText.Split(new Char[] { ' ' })[0];
            //t.numberNumber = titleCols[1].InnerText.Split(new Char[] { ' ' })[1];
            //t.name = titleCols[2].InnerText;//.Replace("&nbsp;");
            //t.name = t.name.Replace("&nbsp;", "");
            //t.credits = float.Parse(titleCols[3].InnerText.Split(new Char[] { ' ' })[0]);


            ////Check if the next row describes prereqs
            //if (oneCourse[k].SelectNodes(".//td")[1].InnerText == "Prerequisite:")
            //{
            //    t.prereqCourses = (oneCourse[k].SelectNodes(".//td")[2].InnerText);
            //    k++;
            //}

            //if (oneCourse[k].SelectNodes(".//td")[1].InnerText == "Special Note:")
            //{
            //    t.specialNote = parseSpecialNote(oneCourse[k].SelectNodes(".//td")[2].InnerText);
            //    k++;
            //}

            //k++;

            ////process lectures, tutorials, labs... you know, the easy stuff
            //bool firstPass = true;
            //List<lecture> theLectures = new List<lecture>();
            //List<HtmlNode> oneLecture = new List<HtmlNode>();
            //for (int j = k; j < oneCourse.Count(); j++) //cycle through all the rows that give the information of lecture
            //{

            //    if (oneCourse[j].SelectNodes(".//td")[2].InnerText.Contains("Lect")) //this row is a lecture row; until the next lecture row or until the end of this course's section, the information is about this lecture's tutorials and labs
            //    {
            //        if (firstPass == true)
            //        {
            //            firstPass = false;
            //            oneLecture.Add(oneCourse[j]);

            //        }
            //        else
            //        {
            //            theLectures.Add(parseLecture(oneLecture)); //send one block of lecture to be parsed: a lecture and all it's tutorials and labs
            //            oneLecture.Clear();
            //            oneLecture.Add(oneCourse[j]);

            //        }

            //    }

            //    else //this row is another row that is between two lectture rows and will be sent for parsing as part of the oneLecture list.
            //    {
            //        oneLecture.Add(oneCourse[j]);


            //    }

            //}
            //theLectures.Add(parseLecture(oneLecture));

            //t.lectures = theLectures;

            //return t;



        }

        public lab parseLab(List<HtmlNode> labz)
        {
            lab result = new lab();


            return result;

        }

        public tutorial parseTutorial(List<HtmlNode> t)
        {

            tutorial result = new tutorial();

            if (t.Count() < 1)
                return null;

            //parse first row here, it's the tutorial row
            if (t[0].SelectNodes(".//td")[2].InnerText.Contains("Tut"))
            {
                result.isMock = false;

                if (t[0].SelectNodes(".//td")[2].InnerText.Contains("Canceled"))
                {
                    result.isCancelled = true;
                }
                else
                {
                    result.isCancelled = false;
                }

                switch (t[0].SelectNodes(".//td")[1].InnerText.Substring(t[0].SelectNodes(".//td")[1].InnerText.IndexOf("/") + 1)) //first row, second column, discards start 
                {
                    case "2":
                        result.season = seasons.fall;
                        break;
                    case "3":
                        result.season = seasons.fall_winter;
                        break;
                    case "4":
                        result.season = seasons.winter;
                        break;
                    case "1":
                        result.season = seasons.summer;
                        break;

                }

                result.section = t[0].SelectNodes(".//td")[2].InnerText.Split()[1];

                result.time = parseTime(t[0].SelectNodes(".//td")[3].InnerText);

                //result.place = t[0].SelectNodes(".//td")[4].InnerText;
                result.place = parseLocation(t[0].SelectNodes(".//td")[4].InnerText);


                //labs now
                List<lab> theLabs = new List<lab>();
                //List<HtmlNode> oneLab = new List<HtmlNode>();
                //bool firstPass = true;
                if (t.Count() > 1)
                {
                    for (int i = 1; i < t.Count(); i++)
                    {
                        lab oneLab = new lab();

                        if (t[i].SelectNodes(".//td")[2].InnerText.Contains("Canceled"))
                        {
                            oneLab.isCancelled = true;
                        }
                        else
                        {
                            oneLab.isCancelled = false;
                        }



                        switch (t[i].SelectNodes(".//td")[1].InnerText.Substring(t[i].SelectNodes(".//td")[1].InnerText.LastIndexOf("/") + 1))
                        {
                            case "2":
                                oneLab.season = seasons.fall;
                                break;
                            case "3":
                                oneLab.season = seasons.fall_winter;
                                break;
                            case "4":
                                oneLab.season = seasons.winter;
                                break;
                            case "1":
                                oneLab.season = seasons.summer;
                                break;
                        }

                        oneLab.section = (t[i].SelectNodes(".//td")[2].InnerText);
                        oneLab.time = parseTime(t[i].SelectNodes(".//td")[3].InnerText);
                        oneLab.week = parseWeek(t[i].SelectNodes(".//td")[3].InnerText);
                        //oneLab.place = t[i].SelectNodes(".//td")[4].InnerText;
                        oneLab.place = parseLocation(t[i].SelectNodes(".//td")[4].InnerText);


                        theLabs.Add(oneLab);
                    }
                    result.labs = theLabs;
                }
                else
                {
                    result.labs = null;
                }
            }
            else
            {
                List<lab> theLabs = new List<lab>();
                foreach (HtmlNode o in t)
                {
                    lab oneLab = new lab();
                    if (o.SelectNodes(".//td")[2].InnerText.Contains("Canceled"))
                    {
                        oneLab.isCancelled = true;
                    }
                    else
                    {
                        oneLab.isCancelled = false;
                    }


                    switch (o.SelectNodes(".//td")[1].InnerText.Substring(o.SelectNodes(".//td")[1].InnerText.LastIndexOf("/") + 1))
                    {
                        case "2":
                            oneLab.season = seasons.fall;
                            break;
                        case "3":
                            oneLab.season = seasons.fall_winter;
                            break;
                        case "4":
                            oneLab.season = seasons.winter;
                            break;
                        case "1":
                            oneLab.season = seasons.summer;
                            break;
                    }

                    oneLab.section = (o.SelectNodes(".//td")[2].InnerText.Substring(o.SelectNodes(".//td")[2].InnerText.LastIndexOf("nbsp;") + 1)).Split()[1];
                    oneLab.time = parseTime(o.SelectNodes(".//td")[3].InnerText);
                    oneLab.week = parseWeek(o.SelectNodes(".//td")[3].InnerText);
                    oneLab.place = parseLocation(o.SelectNodes(".//td")[4].InnerText);


                    theLabs.Add(oneLab);

                }
                result.labs = theLabs;
                result.isMock = true;
                result.section = null;



            }
            return result;

            //tutorial result = new tutorial();

            //if (t.Count() < 1)
            //    return null;

            ////parse first row here, it's the tutorial row
            //if (t[0].SelectNodes(".//td")[2].InnerText.Contains("Tut"))
            //{
            //    result.isMock = false;

            //    if (t[0].SelectNodes(".//td")[2].InnerText.Contains("Canceled"))
            //    {
            //        result.isCancelled = true;
            //    }
            //    else
            //    {
            //        result.isCancelled = false;
            //    }

            //    switch (t[0].SelectNodes(".//td")[1].InnerText.Substring(t[0].SelectNodes(".//td")[1].InnerText.IndexOf("/") + 1)) //first row, second column, discards start 
            //    {
            //        case "2":
            //            result.season = seasons.fall;
            //            break;
            //        case "3":
            //            result.season = seasons.fall_winter;
            //            break;
            //        case "4":
            //            result.season = seasons.winter;
            //            break;
            //        case "1":
            //            result.season = seasons.summer;
            //            break;

            //    }

            //    result.section = t[0].SelectNodes(".//td")[2].InnerText.Split()[1];

            //    result.time = parseTime(t[0].SelectNodes(".//td")[3].InnerText);

            //    //result.place = t[0].SelectNodes(".//td")[4].InnerText;
            //    result.place = parseLocation(t[0].SelectNodes(".//td")[4].InnerText);


            //    //labs now
            //    List<lab> theLabs = new List<lab>();
            //    //List<HtmlNode> oneLab = new List<HtmlNode>();
            //    //bool firstPass = true;
            //    if (t.Count() > 1)
            //    {
            //        for (int i = 1; i < t.Count(); i++)
            //        {
            //            lab oneLab = new lab();

            //            if (t[i].SelectNodes(".//td")[2].InnerText.Contains("Canceled"))
            //            {
            //                oneLab.isCancelled = true;
            //            }
            //            else
            //            {
            //                oneLab.isCancelled = false;
            //            }



            //            switch (t[i].SelectNodes(".//td")[1].InnerText.Substring(t[i].SelectNodes(".//td")[1].InnerText.LastIndexOf("/") + 1))
            //            {
            //                case "2":
            //                    oneLab.season = seasons.fall;
            //                    break;
            //                case "3":
            //                    oneLab.season = seasons.fall_winter;
            //                    break;
            //                case "4":
            //                    oneLab.season = seasons.winter;
            //                    break;
            //                case "1":
            //                    oneLab.season = seasons.summer;
            //                    break;
            //            }

            //            oneLab.section = (t[i].SelectNodes(".//td")[2].InnerText);
            //            oneLab.time = parseTime(t[i].SelectNodes(".//td")[3].InnerText);
            //            oneLab.week = parseWeek(t[i].SelectNodes(".//td")[3].InnerText);
            //            //oneLab.place = t[i].SelectNodes(".//td")[4].InnerText;
            //            oneLab.place = parseLocation(t[i].SelectNodes(".//td")[4].InnerText);


            //            theLabs.Add(oneLab);
            //        }
            //        result.labs = theLabs;
            //    }
            //    else
            //    {
            //        result.labs = null;
            //    }
            //}
            //else
            //{
            //    List<lab> theLabs = new List<lab>();
            //    foreach (HtmlNode o in t)
            //    {
            //        lab oneLab = new lab();
            //        if (o.SelectNodes(".//td")[2].InnerText.Contains("Canceled"))
            //        {
            //            oneLab.isCancelled = true;
            //        }
            //        else
            //        {
            //            oneLab.isCancelled = false;
            //        }


            //        switch (o.SelectNodes(".//td")[1].InnerText.Substring(o.SelectNodes(".//td")[1].InnerText.LastIndexOf("/") + 1))
            //        {
            //            case "2":
            //                oneLab.season = seasons.fall;
            //                break;
            //            case "3":
            //                oneLab.season = seasons.fall_winter;
            //                break;
            //            case "4":
            //                oneLab.season = seasons.winter;
            //                break;
            //            case "1":
            //                oneLab.season = seasons.summer;
            //                break;
            //        }

            //        oneLab.section = (o.SelectNodes(".//td")[2].InnerText.Substring(o.SelectNodes(".//td")[2].InnerText.LastIndexOf("nbsp;") + 1)).Split()[1];
            //        oneLab.time = parseTime(o.SelectNodes(".//td")[3].InnerText);
            //        oneLab.week = parseWeek(o.SelectNodes(".//td")[3].InnerText);
            //        oneLab.place = parseLocation(o.SelectNodes(".//td")[4].InnerText);


            //        theLabs.Add(oneLab);

            //    }
            //    result.labs = theLabs;
            //    result.isMock = true;
            //    result.section = null;



            //}
            //return result;

        }


        public lecture parseLecture(List<HtmlNode> l)
        {

            lecture result = new lecture();
            //parse first row here, it's the lecture    row

            if (l[0].SelectNodes(".//td")[2].InnerText.Contains("Canceled"))
            {
                result.isCancelled = true;
            }
            else
            {
                result.isCancelled = false;
            }

            switch (l[0].SelectNodes(".//td")[1].InnerText) //first row, second column 
            {
                case "/2":
                    result.season = seasons.fall;
                    break;
                case "/3":
                    result.season = seasons.fall_winter;
                    break;
                case "/4":
                    result.season = seasons.winter;
                    break;
                case "/1":
                    result.season = seasons.summer;
                    break;

            }

            result.section = l[0].SelectNodes(".//td")[2].InnerText.Split()[1];

            result.time = parseTime(l[0].SelectNodes(".//td")[3].InnerText);

            result.place = parseLocation(l[0].SelectNodes(".//td")[4].InnerText);

            //result.prof = l[0].SelectNodes(".//td")[5].InnerText;
            result.prof = parseProf(l[0].SelectNodes(".//td")[5].InnerText);

            //tutorials now
            List<tutorial> theTutorials = new List<tutorial>();
            List<HtmlNode> oneTutorial = new List<HtmlNode>();
            bool firstPass = true;
            if (l.Count() > 1)
            {
                for (int i = 1; i < l.Count(); i++)
                {
                    if (l[i].SelectNodes(".//td")[2].InnerText.Contains("Tut"))
                    {
                        if (firstPass == true)
                        {
                            firstPass = false;
                            oneTutorial.Add(l[i]);

                        }
                        else
                        {
                            theTutorials.Add(parseTutorial(oneTutorial));
                            oneTutorial.Clear();
                            oneTutorial.Add(l[i]);
                        }
                    }
                    else
                    {
                        oneTutorial.Add(l[i]);

                    }


                }

            }
            else
            {
                result.tutorials = null;

            }
            if (oneTutorial != null)
                theTutorials.Add(parseTutorial(oneTutorial));

            result.tutorials = theTutorials;



            return result;
            //lecture result = new lecture();
            ////parse first row here, it's the lecture    row

            //if (l[0].SelectNodes(".//td")[2].InnerText.Contains("Canceled"))
            //{
            //    result.isCancelled = true;
            //}
            //else
            //{
            //    result.isCancelled = false;
            //}

            //switch (l[0].SelectNodes(".//td")[1].InnerText) //first row, second column 
            //{
            //    case "/2":
            //        result.season = seasons.fall;
            //        break;
            //    case "/3":
            //        result.season = seasons.fall_winter;
            //        break;
            //    case "/4":
            //        result.season = seasons.winter;
            //        break;
            //    case "/1":
            //        result.season = seasons.summer;
            //        break;

            //}

            //result.section = l[0].SelectNodes(".//td")[2].InnerText.Split()[1];

            //result.time = parseTime(l[0].SelectNodes(".//td")[3].InnerText);

            //result.place = parseLocation(l[0].SelectNodes(".//td")[4].InnerText);

            ////result.prof = l[0].SelectNodes(".//td")[5].InnerText;
            //result.prof = parseProf(l[0].SelectNodes(".//td")[5].InnerText);

            ////tutorials now
            //List<tutorial> theTutorials = new List<tutorial>();
            //List<HtmlNode> oneTutorial = new List<HtmlNode>();
            //bool firstPass = true;
            //if (l.Count() > 1)
            //{
            //    for (int i = 1; i < l.Count(); i++)
            //    {
            //        if (l[i].SelectNodes(".//td")[2].InnerText.Contains("Tut"))
            //        {
            //            if (firstPass == true)
            //            {
            //                firstPass = false;
            //                oneTutorial.Add(l[i]);

            //            }
            //            else
            //            {
            //                theTutorials.Add(parseTutorial(oneTutorial));
            //                oneTutorial.Clear();
            //                oneTutorial.Add(l[i]);
            //            }
            //        }
            //        else
            //        {
            //            oneTutorial.Add(l[i]);

            //        }


            //    }

            //}
            //else
            //{
            //    result.tutorials = null;

            //}
            //if (oneTutorial != null)
            //    theTutorials.Add(parseTutorial(oneTutorial));

            //result.tutorials = theTutorials;



            //return result;

        }

        public int parseWeek(string p)
        {
            if (p.Contains("Week"))
            {
                return int.Parse(p.Split()[3].Trim(new char[] { 'W', 'e', 'k', '(', ')' }));
            }
            else
            {
                return 0;
            }

        }

        public List<timeBlock> parseTime(string p)
        {

            List<timeBlock> theTimes = new List<timeBlock>();
            string days = p.Split()[0];
            string time = p.Split()[1].Trim(new char[] { ' ', '(', ')' });
            string startH = time.Split(new char[] { ':', '-' })[0];
            string startM = time.Split(new char[] { ':', '-' })[1];
            string endH = time.Split(new char[] { ':', '-' })[2];
            string endM = time.Split(new char[] { ':', '-' })[3];


            for (int q = 0; q < 7; q++)
            {
                if (days[q] != '-')
                {
                    switch (q)
                    {
                        case 0:
                            timeBlock m = new timeBlock();
                            m.day = daysWeek.monday;
                            theTimes.Add(m);
                            break;
                        case 1:
                            timeBlock tu = new timeBlock();
                            tu.day = daysWeek.tuesday;
                            theTimes.Add(tu);
                            break;
                        case 2:
                            timeBlock w = new timeBlock();
                            w.day = daysWeek.wednesday;
                            theTimes.Add(w);
                            break;
                        case 3:
                            timeBlock th = new timeBlock();
                            th.day = daysWeek.thursday;
                            theTimes.Add(th);
                            break;
                        case 4:
                            timeBlock f = new timeBlock();
                            f.day = daysWeek.friday;
                            theTimes.Add(f);
                            break;
                        case 5:
                            timeBlock sa = new timeBlock();
                            sa.day = daysWeek.saturday;
                            theTimes.Add(sa);
                            break;
                        case 6:
                            timeBlock su = new timeBlock();
                            su.day = daysWeek.sunday;
                            theTimes.Add(su);
                            break;
                    }

                }

            }



            foreach (timeBlock a in theTimes)
            {
                a.startHour = startH;
                a.startMinute = startM;
                a.endHour = endH;
                a.endMinute = endM;
            }


            return theTimes;

            //List<timeBlock> theTimes = new List<timeBlock>();
            //string days = p.Split()[0];
            //string time = p.Split()[1].Trim(new char[] { ' ', '(', ')' });
            //string startH = time.Split(new char[] { ':', '-' })[0];
            //string startM = time.Split(new char[] { ':', '-' })[1];
            //string endH = time.Split(new char[] { ':', '-' })[2];
            //string endM = time.Split(new char[] { ':', '-' })[3];


            //for (int q = 0; q < 7; q++)
            //{
            //    if (days[q] != '-')
            //    {
            //        switch (q)
            //        {
            //            case 0:
            //                timeBlock m = new timeBlock();
            //                m.day = daysWeek.monday;
            //                theTimes.Add(m);
            //                break;
            //            case 1:
            //                timeBlock tu = new timeBlock();
            //                tu.day = daysWeek.tuesday;
            //                theTimes.Add(tu);
            //                break;
            //            case 2:
            //                timeBlock w = new timeBlock();
            //                w.day = daysWeek.wednesday;
            //                theTimes.Add(w);
            //                break;
            //            case 3:
            //                timeBlock th = new timeBlock();
            //                th.day = daysWeek.thursday;
            //                theTimes.Add(th);
            //                break;
            //            case 4:
            //                timeBlock f = new timeBlock();
            //                f.day = daysWeek.friday;
            //                theTimes.Add(f);
            //                break;
            //            case 5:
            //                timeBlock sa = new timeBlock();
            //                sa.day = daysWeek.saturday;
            //                theTimes.Add(sa);
            //                break;
            //            case 6:
            //                timeBlock su = new timeBlock();
            //                su.day = daysWeek.sunday;
            //                theTimes.Add(su);
            //                break;
            //        }

            //    }

            //}



            //foreach (timeBlock a in theTimes)
            //{
            //    a.startHour = startH;
            //    a.startMinute = startM;
            //    a.endHour = endH;
            //    a.endMinute = endM;
            //}


            //return theTimes;

        }

        public prereqs parsePrereqs(string line)
        {
            prereqs result = new prereqs();


            return result;
        }

        public string parseSpecialNote(string note)
        {

            return note;
        }

        public professor parseProf(string p)
        {
            professor result = new professor();
            string[] temp = p.Split(new char[] { ',' });
            result.LastName = temp[0].Trim();

            if (temp.Length == 1)
            {
                return result;
            }
            result.FirstName = temp[1].Trim();
            return result;
        }

        public location parseLocation(string w)
        {

            location result = new location();
            string[] temp = w.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            if (temp.Length == 0)
                return null;
            result.campus = temp[0];

            if (temp.Length == 1)
                return result;

            result.building = temp[1].Split(new char[] { '-' })[0];

            if (temp.Length == 2)
            {
                result.room = temp[1].Split(new char[] { '-' })[1];
                return result;
            }

            result.room = temp[1].Split(new char[] { '-' })[1] + " " + temp[2];
            return result;
        }



        //private LinkedList<string> processed_data()
        //{
        //    LinkedList<string> values = new LinkedList<string>();
        //    try
        //    {

        //        //tables = doc.DocumentNode.SelectNodes("//table");
        //        rows = tables[0].SelectNodes(".//tr");

        //        for (int i = 0; i < rows.Count; ++i)
        //        {

        //            // Iterate all columns in this row
        //            HtmlNodeCollection cols = rows[i].SelectNodes(".//td");
        //            for (int j = 0; j < cols.Count; ++j)
        //            {
        //                values.AddLast(cols[j].InnerHtml);
        //            }
        //        }

        //    }
        //    catch (Exception error)
        //    {

        //        Console.WriteLine(error.ToString());

        //    }


        //    return values;

        //}



    }

    [Serializable()]
    public class course
    {
        public bool validCourse;
        public string numberBranch;
        public string name;
        public string numberNumber;
        public float credits;
        public bool cancelled;
        public List<lecture> lectures;
        //public prereqs prereqCourses;
        public string prereqCourses;
        public string specialNote;


    }

    public enum seasons { summer, fall, winter, fall_winter };
    public enum daysWeek { monday, tuesday, wednesday, thursday, friday, saturday, sunday };
    public enum campuses { loy, sgw };
    public enum buildings { H, FG, MB }; //totally incomplete

    [Serializable()]
    public class lecture
    {

        public seasons season; // Summer, Fall, Fall&Winter, Winter  
        public string section;
        public List<timeBlock> time;
        public professor prof;
        //public string prof;
        public location place;
        //public string place;
        public List<tutorial> tutorials;
        public bool isCancelled;

    }
    [Serializable()]
    public class tutorial
    {
        public seasons season; // Summer, Fall, Fall&Winter, Winter 
        public string section;
        public List<timeBlock> time;
        public location place;
        //public string place;
        public List<lab> labs;
        public bool isMock = false;
        public bool isCancelled;

    }
    [Serializable()]
    public class lab
    {
        public seasons season; // Summer, Fall, Fall&Winter, Winter  
        public string section;
        public List<timeBlock> time;
        public location place;
        //public string place;
        public int week; // as in week 1 or week 2
        public bool isCancelled;

    }
    [Serializable()]
    public class professor
    {
        public string FirstName;
        public string LastName;

    }
    [Serializable()]
    public class timeBlock
    {

        public daysWeek day;
        public string startHour;
        public string startMinute;

        public string endHour;
        public string endMinute;

        //public int duration;
        //public int startTime;
        //public int endTime;

    }

    [Serializable()]
    public class prereqs
    {
        List<course> prereqsCourses;
        List<course> coreqCourses;
    }
    [Serializable()]
    public class location
    {
        //public campuses campus;
        public string campus;
        //public buildings building;
        public string building;
        public string room;


    }


}